1 package net.sourceforge.simplegamenet.framework;
2
3 import java.io.File;
4 import java.io.FileFilter;
5 import java.net.MalformedURLException;
6 import java.net.URI;
7 import java.net.URISyntaxException;
8 import java.net.URL;
9 import java.net.URLClassLoader;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.jar.JarFile;
15 import java.util.jar.Manifest;
16 import javax.swing.*;
17 import net.sourceforge.simplegamenet.framework.model.SimpleGameNetSettings;
18 import net.sourceforge.simplegamenet.framework.transport.GameIdentification;
19 import net.sourceforge.simplegamenet.specs.model.GameFactory;
20
21 /***
22 * A Singleton
23 */
24 public class GameFactoryManager {
25
26 private static GameFactoryManager instance;
27
28 public static GameFactoryManager getInstance() {
29 return instance;
30 }
31
32 public static void loadGamesStaticly(List gameFactoriesList) {
33 ClassLoader gamesClassLoader = GameFactoryManager.class.getClassLoader();
34 instance = new GameFactoryManager(gamesClassLoader, gameFactoriesList);
35 }
36
37 public static void loadGamesDynamically() {
38 try {
39 String gamesPath = createGamesPath();
40 File pathFile = new File(new URI(gamesPath));
41 File[] files = pathFile.listFiles(new JarFileFilter());
42 if (files == null) {
43 JOptionPane.showMessageDialog(null,
44 pathFile.toString() + " does not exist.",
45 "Error loading games", JOptionPane.ERROR_MESSAGE);
46 System.exit(1);
47 }
48 ClassLoader gamesClassLoader = createGamesClassLoader(files, gamesPath);
49 List gameFactoriesList = createGameFactoriesList(files, gamesClassLoader, pathFile);
50 Collections.sort(gameFactoriesList);
51 Thread.currentThread().setContextClassLoader(gamesClassLoader);
52 instance = new GameFactoryManager(gamesClassLoader, gameFactoriesList);
53 } catch (URISyntaxException e) {
54 JOptionPane.showMessageDialog(null,
55 "Error loading games.",
56 "Error loading games", JOptionPane.ERROR_MESSAGE);
57 System.exit(1);
58 }
59 }
60
61 private static String createGamesPath() {
62 String gamesPath = GameFactoryManager.class.getResource(
63 "/" + GameFactoryManager.class.getName().replaceAll("//.", "/") + ".class")
64 .getPath();
65 gamesPath = gamesPath.substring(0, gamesPath.lastIndexOf('/', gamesPath.lastIndexOf('!')))
66 + "/games/";
67 return gamesPath;
68
69 }
70
71 private static ClassLoader createGamesClassLoader(File[] files, String path) {
72 URL[] uRLs = new URL[files.length];
73 for (int i = 0; i < files.length; i++) {
74 try {
75 uRLs[i] = new URL(new URL(path), files[i].getName());
76 } catch (MalformedURLException e) {
77 e.printStackTrace();
78 }
79 }
80 ClassLoader gamesClassLoader = new URLClassLoader(uRLs);
81 return gamesClassLoader;
82 }
83
84 private static List createGameFactoriesList(File[] files, ClassLoader gamesClassLoader,
85 File pathFile) {
86 List gameFactoriesList;
87 gameFactoriesList = new ArrayList();
88 for (int i = 0; i < files.length; i++) {
89 try {
90 JarFile jarFile = new JarFile(files[i]);
91 Manifest manifest = jarFile.getManifest();
92 if (manifest == null) {
93 throw new Exception("No manifest");
94 }
95 Class classInstance = gamesClassLoader.loadClass(
96 manifest.getMainAttributes().getValue("Main-Class"));
97 GameFactory gameFactory = (GameFactory) classInstance.newInstance();
98 if (gameFactoriesList.contains(gameFactory)) {
99 JOptionPane.showMessageDialog(null,
100 files[i].getName() + " has been included twice.",
101 "Error loading a game", JOptionPane.WARNING_MESSAGE);
102 continue;
103 }
104 if (SimpleGameNetSettings.getInstance().getVersion().compareTo(
105 gameFactory.getMinimumSimpleGameNetVersion())
106 < 0) {
107 JOptionPane.showMessageDialog(null,
108 files[i].getName() + " needs SimpleGameNet version "
109 + gameFactory.getMinimumSimpleGameNetVersion()
110 .toString() + ".",
111 "Error loading a game", JOptionPane.WARNING_MESSAGE);
112 continue;
113 }
114 gameFactoriesList.add(gameFactory);
115
116
117
118
119
120
121
122
123
124
125 } catch (Exception e) {
126 JOptionPane.showMessageDialog(null,
127 files[i].getName() + " is not a valid game package.",
128 "Error loading a game", JOptionPane.WARNING_MESSAGE);
129 }
130 }
131 if (gameFactoriesList.size() <= 0) {
132 JOptionPane.showMessageDialog(null,
133 pathFile.toString()
134 + " did not contain any valid game packages.",
135 "Error loading games", JOptionPane.ERROR_MESSAGE);
136 System.exit(1);
137 }
138 return gameFactoriesList;
139 }
140
141
142 private ClassLoader gamesClassLoader;
143 private List gameFactoriesList;
144
145 private GameFactoryManager(ClassLoader gamesClassLoader, List gameFactoriesList) {
146 this.gamesClassLoader = gamesClassLoader;
147 this.gameFactoriesList = gameFactoriesList;
148 }
149
150 public ClassLoader getGamesClassLoader() {
151 return gamesClassLoader;
152 }
153
154 public GameFactory[] getGameFactories() {
155 return (GameFactory[]) gameFactoriesList.toArray(new GameFactory[gameFactoriesList.size()]);
156 }
157
158 public GameFactory getGameFactory(GameIdentification gameIdentification) {
159 for (Iterator it = gameFactoriesList.iterator(); it.hasNext();) {
160 GameFactory gameFactory = (GameFactory) it.next();
161 if (gameFactory.getName().equals(gameIdentification.getName())
162 && gameFactory.getAuthor().equals(gameIdentification.getAuthor())) {
163 return gameFactory;
164 }
165 }
166 return null;
167 }
168
169 private static class JarFileFilter implements FileFilter {
170
171 public boolean accept(File pathname) {
172 return pathname.getName().endsWith(".jar");
173 }
174
175 }
176
177 }